编者按:本文整理自龙蜥大讲堂技术解读,分享主题为《构建商用密码操作系统》,直播视频回放已上线至龙蜥社区官网(文末阅读原文直接跳转):首页-支持-视频,欢迎观看。作者张天佳,来⾃阿⾥云操作系统团队,是龙蜥社区商密软件栈 SIG 负责人。主要研究⽅向为 OS 安全,包括可信计算,机密计算,⽬前专注于国内商⽤密码的⼯程开发以及推广⼯作,我们团队主导开发了 Linux 内核、libgcrypt、OpenSSL 等多个项⽬中主要的商密算法⼯程化以及优化实现。
缘起
说到密码算法,⼤家⼀定很熟悉 MD5、AES、RSA 这些通用的国际标准算法,这也是目前我们普遍采⽤的密码学算法,它们在数据安全、互联网、通信、区块链等众多领域都有着⼴泛的应用。
众所周知,这些算法标准都是国外制定的,⼯程实现也主要由国外主导,在某些情况下这会对国内信息安全有不利影响。当下有实力的国家,甚⾄有些大公司都制定了自己的算法标准。密码算法是保障信息和数据安全的核⼼技术,随着近年来外部的国际贸易冲突和技术封锁,国内互联网的快速发展,我们不能单⼀依赖国外的的技术标准和产品,增强我国⾏业信息系统的安全可信显得尤为必要和迫切。商⽤密码算法给我们提供了⼀个新的选择,使得我们可以完全使用商密技术来构建⽹络和数据安全环境。因此,建立⼀套商⽤密码的基础设施就显得尤为必要和迫切,本次分享带给⼤家我们是如何基于 Linux 内核构建起商⽤密码基础设施,基于商⽤密码的应⽤,以及未来的思考和规划。
商用密码简介及现状
商⽤密码标准完全由中国密码管理局制定,作为中国⾃主研发可控的密码算法,主要的⼯程实现也基本是国内开发⼈员完成的,这对于摆脱国外的密码技术和产品依赖,以及保护国内数据和网络安全是非常有利的。商用密码,简称商密,拼⾳缩写是 SM,⼝语中⼀般称呼为国密,通俗来说可以认为是密码算法的国产化,跟其它领域⼀样,中国的商密算法为我们提供了⼀个新的选择,在必要的场合中可以选择替代那些国际主流算法,尤其是当下国际贸易冲突,技术封锁不可忽视的⼤环境下,⼤规模推⼴和采⽤商密算法将为国内重要的网络基础设施提供可靠的数据安全保障。近⼗多年来,国家密码管理局陆续发布了多项商⽤密码⾏业标准,其中⼀些成为国家标准,很多基础类的算法标准也陆续成为 ISO/IEC 国际标准,到⽬前为⽌,商⽤密码标准已经⾮常成熟,也提供了完全⼀致的算法接⼝和⽤户体验,完全可以⽤来替代主流的国际算法。商密算法并不是⼀新技术,⾃ 2012 年以来,SM2/3/4 的商密标准陆续公布,⾄今⼗多年,商密商业应⽤基本处于⼀个相对空⽩的状态,国内的商密软硬件⽣态,技术⽅案实现存在很严重的碎⽚化情况,我们经常可以看到各种个⼈或组织名义开源的⽀持商密算法的库,技术⽅案参差不齐,在安全更新和社区活跃度也做的不够好,这也⼀定程度上限制了商⽤密码的⼤规模应用;商密的推⼴仍然任重道远,需要我们中国基础软件的开发者和⽤户共同努力。
碎⽚化的⽣态就导致没有统⼀的技术⽅案,进而造成商密的产业化应⽤就特别的慢,导致鲜有⼈愿意为反哺商密⽣态,造成这样⼀种恶性循环。尤其是当前的⼤背景下,密码算法的国产化已经势不可挡,这也是我们必须要做的事情。2020 年 1 ⽉ 1 ⽇,《中华⼈⺠共和国密码法》正式实施,从法律层⾯规范了国家商⽤密码的应⽤和管理,这也为推⼴和应⽤商⽤密码提供了必要的法律保障。与国际算法的对比
这⾥是商密算法和国际通⽤算法的⼀个对⽐,可以直观地看到商密的⼀个基本情况:针对各种常⽤的国际能⽤算法类型,⽐如对称算法,公钥算法和消息摘要算法,商密标准都定义了对应的相同功能的商密算法,⽐如 SM4 提供了与 AES 同样的加密强度,并且⽀持各种加密模式;SM2 是基于椭圆曲线的公钥算法,同时定义了⾮对称加解密,数字签名和密钥交换标准,相对于 RSA、SM2 的密钥更短,但⽀持的加密强度却更⾼;SM3 是商密定义的消息摘要算法标准,摘要⻓度是固定的 256 位,强度等同于 SHA256。
除了基础的算法,商密标准也定义了 TLCP 商密双证书协议,⽤以⽀持国内的传输层安全协议。这⾥还有⼀个好消息,今年三⽉份,TLS1.3+ 商密单证书协议正式被国际标准所承认,并且以 RFC8998 标准发布,这意味着我们可以选择在 TLS1.3 协议中使⽤完整的商密套件,⽬前我们也在联系正规浏览器⼚商⽀持这个标准的实施和应⽤。同时商密标准也定义了使⽤商密算法的 X509 证书,使⽤ SM3 哈希算法,SM2 算法作为数字签名,证书类型 SM2-with-SM3。对开发者来说,商密提供了⼀个选择,可以选择从国际通⽤算法平滑迁移过来。除此之外,商密还有其它⼀些算法标准,是不太常⽤的,⽐如 SM9、ZUC 算法等。商密基础设施架构
万事俱备,有了基础商密算法⽀持,我们便可以构建出⼀个围绕商密算法展开的基础软件⽣态。这是⼀个商密⽣态的垂直场景,也是我们在 Anolis OS 上的商密⽣态架构,同时它也是⼀个全栈商密解决⽅案:从底层固件、内核、到基础密码学库,在主要链路上做商密改造,最终形成⼀个完整的基于商密的安全信任链条。图上右边是⼀些垂直的商密应⽤场景,⽐如 SecureBoot、IMA、内核模块签名、⽂件完整性校验等。
到⽬前为⽌,我们已经在 Linux 内核、BabaSSL、libgcrypt、Gnulib 等主流的基础组件中⽀持了商密算法,这部分的⼯作都已经回馈到了上游开源社区,有兴趣的开发者可以直接拿来使⽤或者作为参考,⽬前实现的特性已经全部通过 Anolis 商密版 OS 输出,关于这个商密版的 OS,后⾯会做⼀个详细介绍。从中也能看到,商密⽣态涉及到的软件栈⾮常多,形态也是各种各样,要逐步完善这个⽣态,还有很⻓的路要⾛。近⼏年的国际技术封锁也给了我们做这件事的决⼼和动⼒。⽬前我们已经和 ARM,海光等⼚商有⼀些合作,也⾮常欢迎业界有兴趣的开发者能够参与到社区,⼀起来做这个事情,之后我们的⼯作都会在 Anolis 社区以开源⽅式运作,秉着开放包容态度,继续补充完善这个⽣态,最终达到的⼀个⽬标是:整个安全信任链是完全建⽴在商密算法之上。
BabaSSL 是主打商密的密码算法库,与 OpenSSL1.1.1 保持兼容,作为商密的密码算法解决⽅案⽽诞⽣。BabaSSL 是基于之前蚂蚁集团和阿⾥集团内部的 OpenSSL 版本合并⽽来,我们希望将 BabaSSL 打造成⼀个灵活、⼩巧并且健壮的基础密码学库,项⽬主体已于2020 年 10 ⽉在 Github 开源(链接见文末),当前开源的版本是 8.2.1,也是⽬前最新的稳定版本。BabaSSL 的主要发起者是蚂蚁集团的杨洋,杨洋也是 OpenSSL 项⽬在国内唯⼀的 Maintainer,主导开发了其中商密相关的算法,并且组织制定了 RFC8998 规范,关于这个规范,后⾯也会详细介绍。BabaSSL ⽬前完全以社区⽅式动作,已经组建了技术委员会,由阿⾥和⾏业内其它公司主要开发者组成,技术委员会决策项⽬的发展⽅向以及运营⼯作。BabaSSL ⽬前在阿⾥集团和蚂蚁集团内部得到了⾮常⼴泛的使⽤。从具体场景来看,有如下三个⽅⾯,分别是存储、网络和端上的设备。其中网络服务的场景,是 BabaSSL 最⼤的⽀撑场景,例如淘宝、天猫、阿⾥云等各种涉及到链路加密的服务器端。此外移动端 App,例如⽀付宝⼿机 App 中集成了 BabaSSL 来实现多种密码学的能力。以下是 BabaSSL 当前最新稳定版本 8.2.1 的主要特⾊功能特性:- 基于 OpenSSL1.1.1,具备 OpenSSL1.1.1 的全部能⼒并且保持兼容
- ⽀持商密 SM2、SM3 和 SM4,SM4GCM/CCM 模式算法
- 更加完善的 SM2 算法⽀持,⽐如 X.509 证书签发、验签的⽀持,这是 OpenSSL1.1.1 欠缺的能力
- GM/T0024 和 TLCP 商密双证书 TLS 协议
- ⽀持 RFC8998:TLS1.3+ 商⽤密码算法套件
- 提供了对 IETF 正在标准化过程中的 DelegatedCredentials
正在申请软件密码模块⼀级资质
接下来是⼤家很关⼼的 BabaSSL 和 OpenSSL 这种⽼牌的密码算法库之间的区别:从图上可以看到⼀些主要区别:
- 对于⼀些新的密码学技术标准,BabaSSL 会采取⼀种相对激进的策略快速跟进,⽐如在 IETF 中⼀些正在标准化流程中的技术⽅案,例如 delegatedcredentials、compactTLS 等,会进⾏原型的实现和快速跟进,⽽ OpenSSL 则是相对保守,因为 OpenSSL 社区的策略是原则上只实现已经发布了的国际标准和国家标准。
- 在对于商密算法、商密协议、商密的监管合规、云计算⼚商的深度集成、以及国产化硬件等⽅⾯,BabaSSL 会进⾏更加深度和⼴泛的⽀持,而 OpenSSL 则⽀持的⽐较有限。
- 对于 API 的易⽤程度,由于没有历史包袱,所以 BabaSSL 可以提供更加简单易⽤的 API,而 OpenSSL 的 API 则相对复杂。
- 对于资源受限的嵌⼊式设备,BabaSSL会进⾏体积裁剪和内存使⽤量的规划,OpenSSL 则明确表示没有相关的计划。
社区回馈情况
我们在商密⽣态多年的开发⼯作已经全部回馈到了社区,其中绝⼤部分贡献到了主流开源项⽬的上游,包括 OpenSSL、Linux内核、libgcrypt、Gnulib 等,代码量超过 23000 ⾏,图中绿⾊打勾部分都是我们⾃主开发的。经过几年的努力,我们基本建起了商密的基础软件设施,当然这个⽣态不管是横向还是纵向还有很多⼯作要做,需要更多开发者参与进来⼀起建设,我们⾮常欢迎与⼤家⼀起合作。技术解读
OpenSSL ⾥的异步协程机制,这其实是⼀个与今天主题关系不⼤的技术点,主要是国为 OpenSSL ⾥实现了协程,我们也做了⼀些优化,因此做⼀个简单介绍。协程是近⼏年⽐较⽕的⼀个技术,⼀些主流语⾔都或多或少⽀持了协程,⽐如 rust 和 go,Nodejs 和 C 语⾔也有相应的技术或者协程库。但是协程并不是⼀个新技术,Lua 在 18 年前的 5.0 版本中就已经原生⽀持了协程。协程是⽤户⾃主控制的任务调度单元,对操作系统来说是透明的,协程主要应⽤于异步⾼性能场景,⽤户实现负责抽象异步的⾮阻塞和任务单元的调度,提供⼀个协程的开发和运⾏环境。相比于其它⾼性能场景的解决⽅案,协程主要有以下优势:
相⽐于线程,协程更轻量,协程占⽤的资源⾮常少,创建释放也只是⼀个函数调⽤,不需要内核参与。协程是⾃主调度的,⼀般只在阻塞时主动选择调度到其它协程,比起线程的抢占式调度,可控性更⾼,调度的成本也⾮常低,往往只是⼀个函数调⽤。也由于⾃主调度的特点,协程是没有竞争条件的,也就不需要同步,我们知道,同步问题往往是造成多线程编程的恶梦。同步书写,异步执⾏,这是协程相⽐于 nginx、nodejs 这种回调式⾼性能⽅案的最⼤优点,nginx 和 nodejs ⼯程⾥为了实现异步,使⽤了⼤量的回调,甚⾄是多级回调的嵌套,把同步⽅式中的串⾏流程打断到多个回调函数中去执⾏,这当然是很⾼效的模式,也是他们的编程模型决定的,这⼀定程度也导致了程序的可读性差,可维护性低。协程完美的解决了这个问题,在⼏乎不影响性能的前提下,把原来分散到若⼲回调函数中的⽚断代码集中起来,我们可以⽤串⾏⽅式来写异步代码,由协程背后的异步机制来负责调度串⾏的代码⽚断,达到同步书写,异步执⾏的⼀个效果,左图对这个概念表达的不太完整,每个协程是分散在若⼲的⽚断中被执⾏的,但是我们作为开发者,不⽤考虑这些细节,只需要采⽤同步的⽅式来编码即可。⽬前也已经有很多框架采⽤了这种模式,⽐如 openresty,rust ⾥的协程也是这样的模式。图上是⼀个⾮常简单的 TCPecho 服务器伪代码,采⽤了协程机制来实现,这可以让我们对协程有⼀个直观的感受,虽然是伪代码,已经很接近真实的代码实现,在⼀个协程⾥ listen,针对每个连接过来的客户端,再开⼀个协程负责与这个客户端交互,看起来跟同步多线程模型⾮常像,整个过程是⼀个同步的书写模式,但背后是异步的协程在负责调度,性能也⽐同步多线程⾼了许多。
这是⼀个非常典型的场景,OpenSSL 由于需要实现异步 TLS,也实现了⼀个简单的协程机制 ASYNC,可能由于 OpenSSL ⾥场景⽐较简单的缘故,ASYNC 并不⽀持左图中的这种编程模式,主要是它实现的⼀些缺陷造成的:- 引⼊了 dispatcher 作为调度器,并存储协程状态
- 只能在 dispatcher 和唯⼀的协程之间切换
因此我们在 BabaSSL 中引⼊了相应修复⽅案,⽬前已经在 BabaSSL 中得到了⽀持,同时也把这个修复以PR形式提交给了OpenSSL社区。
TLS 协议是基于 TCP 协议,但也有点类似于 TCP,TLS 连接建⽴之前会有⼀个握⼿过程,作为⼀个安全协议,客户端⼀般会验证服务端的身份,这是通过服务端的证书来完成的,经过我们调研,TLS 握⼿过程中的主要⽹络流量就是消耗在证书传输上,尤其是存在过多的中间 CA 会导致证书链成倍的增⼤,这种情况在双向认证时也很明显。因此,在握⼿过程中对证书进⾏压缩就很有必要,从握⼿过程上来看,客户端会在 ClientHello 的扩展中告诉服务器⽀持的压缩算法列表,如果服务端也⽀持压缩,会把压缩过的证书传输给客户端,从而减少不必要的流量消耗。
TLS 证书压缩已经是 RFC 的标准规范,已经率先在 BabaSSL 中得到了⽀持,由于 OpenSSL 相对保守,现在仍然不⽀持这个特性。证书压缩⽬前⽀持三个压缩算法,也⽀持使⽤字典⽅式压缩。开发者可以在 BabaSSL 中体验证书压缩特性:#编译时需要开启TLS证书压缩功能
./config enable-cert-compression
#如果是应⽤开发者,调⽤该API开启证书压缩功能
SSL_CTX_add_cert_compression_alg();
#s_server/s_client命令体验
openssl s_server/s_client -tls1_3 -cert_comp zlib
BabaSSL 在编译时提供了⼀个开关选项,需要在编译配置时打开,如果是应⽤开发者,需要调⽤图中这个 API 在 SSLCTX 中⽀持使⽤证书压缩。⼀般⽤户也可以通过 s_servers_client 命令来体验这个功能,在命令⾏中指定证书压缩选项以及对应的算法。从我们的测试数据来看,普遍可以达到 70% 多的压缩率,甚⾄在使⽤ zstd+ 字典模式时,压缩率可以达到不到 1%,也就是说证书的流量被压缩到了原来的 1% 不到。使⽤证书压缩功能,可以⼤⼤降低握⼿过程中的⽹络传输消耗。从实验数据可以看到,就算加上除证书之外的其它握⼿阶段,在整个握⼿过程中,传输的流量最低只有原来的 20% 多⼀点,我们节省了 80% 的带宽。图中是我们在 Linux 内核对 SM4 算法做的⼀个优化之后的性能数据,对⽐了纯软件实现,AVX 优化实现,AVX2 优化实现的性能,在 1024 ⼤⼩的 block 下,AVX2 的优化相⽐于纯软件实现,CTR 模式下的性能提升了近 8 倍。因为 CBC 和 CFB 加密时有块依赖关系,⽆法进⾏并⾏的优化。不像 AES 这种国际主流算法,各种架构 CPU 都有提供相应的指令集来做加速,SM4 就没有这么好的待遇了,x86 的 CPU 都是没有这样的指令集的,⽬前只有 ARM 的 spec ⾥有优化指令集的定义,因为这是个可选的指令集扩展,因此主流的 ARM 芯⽚默认都选择了不⽀持,当然这也与国密的整个⽣态影响力有关。
不过我们可以借助于 aesni 和 avx 指令集间接优化 SM4,通过两次矩阵转换和⼀次 AESSBOX 查表来实现⼀轮 SM4 优化,并且把这⼀系列操作⽤ AVX 指令集来并⾏化,最⾼可以达到 16 个块并⾏计算,虽然看起来链路更⻓了,但都是在硬件层⾯的优化,实际的性能提升⾮常明显。Anolis商密版OS
以上我们主要介绍了 BabaSSL 和商密基础软件⽣态上做的事情,为了让⽤户能有⼀个直观的体感,更快速的使⽤到商密的技术,我们把所有的技术⽅案都⽀持到了 OS 里,以操作系统的形式提供给有需求的⽤户。为此,龙蜥社区开发了⽀持商⽤密码的 OS 镜像,⽀持了商⽤密码基础设施和应⽤开发⼯具包,同时⽀持了诸多商⽤密码的应⽤场景,对安全合规,数据机密性,以及安全性要求较⾼的⽤户可以基于这个商密⽣态开发出丰富的符合⾃身需求的商密应⽤。Anolis 商密版 OS 是国内⾸家从操作系统层⾯提供商⽤密码的 OS 解决⽅案,在保持 100% 兼容普通 Linux OS 的基础上,从内核到应⽤层基础算法库的全链路上完整⽀持了商密算法,以及基于商密算法的安全认证机制,完全抹平了商密使⽤⻔槛,提供给有需求的⽤户⼀个开箱即⽤的操作系统环境。这⾥⾮常感谢 OpenAnolis 社区提供给我们这样⼀个平台,⽬前项⽬源码完全在社区开源,也欢迎⼤家能够参与以及贡献。有兴趣的⽤户可以从以下地址下载体验,为了⽅便⽤户体验,同时提供了 ISO 镜像和虚拟机镜像(链接见文末)。Anolis 商密版 OS ⽀持以下主要的特⾊功能:除此之外,对于业界领先的 QUICAPI 底层密码学能力,以及 IETF 正在标准化过程中的 DelegatedCredentials 也做了⽀持。商密应用场景
基于 Linux 内核和 BabaSSL 提供的通⽤的商密技术⽅案,可以开发出各种使⽤商密的产品和应⽤,以下⼏个场景是我们做的商密化改造的典型场景。当前的互联⽹时代,密码学应⽤最⼴泛的⽆疑是 HTTPS,众所周知,HTTPS 是构建在 TLS 协议之上的,TLS 是当之⽆愧的互联网通信背后的安全基⽯,因此,我们要在 HTTPS 中使⽤商密算法,只需要考虑在 TLS 协议中⽀持商密算法。⾮常荣幸,IETFRFC8998 规范在 2021 年 3 ⽉正式发布,这个规范是由蚂蚁集团主导完成的,规范完整定义了在 TLS1.3 协议中使⽤商密算法套件的标识,以及 TLS1.3 要求的算法定义。主要内容包括两个对称加密算法 TLS_SM4_GCM_SM3,、数字签名以及在密钥交换中使⽤ SM2 曲线的标识。 当前版本的 BabaSSL 已经完整实现了 TLS1.3 和 RFC8998 中定义的商密套件,图中是 Wireshark 的⼀个抓包,可以看到 TLS 协议是完全构建在商密算法之上的。
另⼀⽅⾯,TLS 的产业化应⽤还要考虑很多问题,从技术上来说,商密的性能是不⾜的,为此,我们为 TLS 商密化做了很多的优化,降低了商密的应⽤成本,使得⼤规模商⽤变得可能。 我们主要以以下⼏个⽅⾯做了优化:
- ⽀持了 TLS 的 offload 到内核,⽬前是纯软的 SWKTLS,这在数据量较⼤的 TLS 场景下减少了不必要的两次数据拷⻉,性能提升⽐较明显
- 更进⼀步的,使⽤AVX2指令集优化了内核SM4算法,达到了近8倍的性能提升,让KTLS可以充分利⽤到这部分性能优化,这个优化⼤幅度提升了TLS商密的性能
还有更彻底的NIC KTLS优化,TLS offload 到硬件⽹卡上去,这需要业界同胞们的共同努力。我们知道,密码学算法从来就是为安全服务的,我们来看两个在安全领域具体商密改造的例⼦。IMA 是 Linux 内核提供⼀个⽂件完整性度量架构,⽤于检测⽂件是否被恶意篡改,内核模块签名的⽬的是类似的,⽤于检测模块的发⾏源头是否可信,是否在分发途中被恶意篡改。它们都提供了自己的签名⼯具,签名⼯具依赖BabaSSL提供的SM2 签名⽂件的能⼒,⽤于在⽤户态做签名。
⽂件签名的验证是在内核⾥完成的,由于内核不能直接使⽤应⽤层的库,为了⽀持在 Linux 内核⾥验证⽂件签名,我们在内核⾥实现了商密 SM2/3/4 算法以及商密证书的⽀持,⽤来验证签名是否合法。通过对相应软件栈的改造,我们完全基于商密算法构建了 IMA 和内核模块签名的安全机制,⽽这些之前都是由国际算法来保证的。以下是我们在 OpenAnolis 上的商密软件栈 SIG,⾮常欢迎有兴趣的开发能参与到社区中来,为中国的基础软件安全添砖加瓦。SIG地址:https://openanolis.cn/sig/crypto
代码库:https://codeup.openanolis.cn/codeup/crypto
Github开源链接:https://github.com/BabaSSL/BabaSSL
ISO 镜像和虚拟机镜像:https://mirrors.openanolis.cn/anolis/8.2/isos/ShangMi/Anolis商密OS最佳实践之IMA商密化
往期精彩回顾
1.关于龙蜥,你关心的问题都在这里
2.Arm加入龙蜥社区并成为理事单位,国内开源再添国际新力量
3.祝贺龙蜥社区理事单位成员入选C++ 标准委员会,首个国内企业代表加入
4.fastFFI 官宣开源,一款高效的Java跨语言通信框架